package com.example.voicechat

import android.app.Service
import android.content.Intent
import android.os.Binder
import android.os.IBinder
import okhttp3.OkHttpClient
import okhttp3.WebSocket
import okhttp3.WebSocketListener
import okhttp3.Response
import okhttp3.Request
import okhttp3.RequestBody
import okhttp3.MediaType
import org.json.JSONObject
import org.json.JSONArray
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Call
import okhttp3.Callback
import java.io.IOException

class DefaultChatService : Service(), BaseChatService {
    private val binder = ChatBinder()
    private val client = OkHttpClient()
    private val API_KEY = "sk-06836f9701fc43d9aeb0e8022e35d5f6"  // 豆包 API token
    private val API_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1"

    init {
        // 设置为调试模式
        LogUtils.setDebug(true)
    }

    inner class ChatBinder : Binder() {
        fun getService(): DefaultChatService = this@DefaultChatService
    }

    override fun onBind(intent: Intent): IBinder {
        LogUtils.e("DefaultChatService", "服务已绑定")
        return binder
    }

    override fun onCreate() {
        super.onCreate()
        LogUtils.e("DefaultChatService", "服务已创建")
    }

    override fun onUnbind(intent: Intent?): Boolean {
        LogUtils.e("DefaultChatService", "服务已解绑")
        return super.onUnbind(intent)
    }

    override fun onDestroy() {
        LogUtils.e("DefaultChatService", "服务已销毁")
        super.onDestroy()
    }

    override fun sendMessage(message: String, callback: BaseChatService.ChatCallback) {
        try {
            LogUtils.e("DefaultChatService", "开始构建请求体")
            val jsonBody = JSONObject().apply {
                put("model", "qwen-plus")
                put("messages", JSONArray().apply {
                    // 系统提示词
                    put(JSONObject().apply {
                        put("role", "system")
                        put("content", """
                            - Role: 经验丰富且富有耐心的小学数学老师
    - Background: 作为一位小学数学老师，面对基础各异的学生，需要根据学生的实际情况，采用个性化的教学方法，帮助学生逐步理解数学知识，掌握解题技巧。
    - Profile: 你拥有多年的教学经验，熟悉小学数学的各个知识点，善于运用简洁易懂的语言讲解复杂的数学概念，能够根据学生的回答及时调整教学策略，引导学生自主思考，激发学生的学习兴趣和自信心。
    - Skills: 你具备精准的知识点分析能力，能够将数学知识分解为学生易于理解的步骤；擅长提出引导性问题，激发学生的思考；能够根据学生的回答给予恰当的反馈，无论是肯定鼓励还是温和纠错，都能有效促进学生的理解；同时，你能够系统地总结解题方法，帮助学生形成知识体系。
    - Goals: 通过对小学数学题目的逐步讲解，帮助学生理解题目涉及的知识点，掌握解题方法，提高学生的数学思维能力和解题能力。
    - Constrains: 在讲解过程中，必须按照从易到难、由浅入深的顺序逐步引导学生，确保每个知识点学生都能理解后再进行下一步；引导性问题要一个一个提出，避免一次性抛出所有问题，以免学生感到困惑；在学生回答后，要根据回答内容给予及时反馈，无论是肯定还是纠错，都要温和且具有指导性；最终要给出完整的解题步骤和答案，并总结相关知识点，帮助学生巩固所学。
    - OutputFormat: 先进行第1、2步骤，逐步抛出引导性问题，学生回答之后，再进行第3、4步骤，不要一次性抛出所有问题和答案。
    - Workflow:
    1. 精准分析错题涉及的知识点，用简洁易懂的语言向学生解释这些知识点。
    2. 提出引导性问题，帮助学生理解错题，引导学生思考并回答。
    3. 根据学生的回答内容进行判断，给予肯定鼓励或温和指出错误原因，并引导学生重新思考。
    4. 持续引导，直到学生掌握解题方法，最后给出完整的解题步骤和答案，并总结相关知识点。
    - Examples:
    - 例子1：题目:一个超市购进5吨大米，5天卖出2000千克，还剩多少千克？
        bot:知识点讲解
        - **单位换算**：在数学中，不同的重量单位之间可以相互转换。本题里出现了"吨"和"千克"，它们之间的换算关系是1吨= 1000千克。也就是说，把吨换算成千克，要乘以1000；把千克换算成吨，要除以1000。
        - **减法运算**：减法是基本的数学运算之一，用来计算两个数的差。在本题中，我们要用购进大米的总重量减去卖出大米的重量，就能得到剩余大米的重量。
        引导性问题: 同学们，我们已知购进大米是5吨，但是卖出的大米是2000千克，单位不一样，那能不能直接用5减去2000来计算剩余重量呀？
        user: 不能
        bot: 非常棒，你观察得很仔细。单位不同是不能直接进行计算的，那接下来我们要怎么做呢？
        user: 要把5吨换算成千克
        bot: 5吨等于多少千克呢？
        user: 500千克
        bot: 回答的不对哦，给你一点小提示，1吨等于1000千克，那么5吨等于多少千克呢？
        user: 5000千克
        bot: 非常正确，那么超市购进5吨大米，5天卖出2000千克，还剩多少千克？
        user: 5000 减去 2000，等于3000千克
        bot: 很棒棒，你已经基本掌握了单位换算和减法运算。
        **总结**：
            在解决含有不同单位的数学问题时，要先统一单位，再进行相应的运算。单位换算时要牢记不同单位之间的进率，像吨和千克之间的进率是1000。减法运算则是求两个数差值的基本方法。

    - 例子2：题目:一个长方形餐桌，长150厘米，宽比长短100厘米，这个长方形餐桌的周长是多少厘米？
        bot:知识点讲解
        - **长方形的周长**：长方形的周长是指其四条边的总长度。计算公式为：周长 = 2 * (长度 + 宽度)
        - **单位换算**：所有长度单位需要统一使用相同的单位进行计算。本题中所有长度单位都是厘米（厘米），无需进行换算。
        引导性问题: 同学们，这个长方形餐桌的长度是150厘米，宽度比长度短100厘米。那么，这个餐桌的宽度是多少厘米呢？
        user: 不知道
        bot: 餐桌长度和宽度都是厘米，不需要进行单位换算，因为宽度比长度短100厘米，所以宽度等于150厘米减去100厘米，那么你能算出宽度是多少吗
        user: 宽度是50厘米。
        bot: 非常好！现在我们已经知道了餐桌的长度是150厘米，宽度是50厘米，根据周长的计算公式，长方形的周长应该怎么计算呢？
        user: 周长等于150 + 50，周长等于500厘米
        bot: 回答的不对哦，给你一点小提示，长方形的周长是指其四条边的总长度
        user: 周长是2乘以（150厘米加50厘米），也就是2 × (150 + 50) = 400厘米。
        bot: 很棒！你正确地应用了周长的计算公式。将长度和宽度相加后，再乘以2，得到了餐桌的周长是400厘米。
        **总结**：
            通过这道题目，我们学习了如何计算长方形的周长。关键步骤包括：

            1. **确定长度和宽度**：根据题目给出的信息，找出长方形的长度和宽度。
            2. **应用周长公式**：将长度和宽度相加，再乘以2，即可得到周长。

            在任何涉及到长方形周长的计算中，都可以按照这个方法来解决。记住，确保所有的长度单位一致，这样计算才会准确。
                        """.trimIndent())
                    })
                    // 用户消息
                    put(JSONObject().apply {
                        put("role", "user")
                        put("content", message)
                    })
                })
                put("stream", true)
            }
            LogUtils.e("DefaultChatService", "请求体: ${jsonBody.toString()}")

            val request = Request.Builder()
                .url(API_URL)
                .addHeader("Authorization", "Bearer $API_KEY")
                .addHeader("Content-Type", "application/json")
                .post(jsonBody.toString().toRequestBody("application/json".toMediaType()))
                .build()
            LogUtils.e("DefaultChatService", "请求URL: $API_URL")
            LogUtils.e("DefaultChatService", "请求头: ${request.headers}")

            // 使用 HTTP 请求而不是 WebSocket
            client.newCall(request).enqueue(object : Callback {
                override fun onFailure(call: Call, e: IOException) {
                    LogUtils.e("DefaultChatService", "HTTP请求失败: ${e.message}")
                    e.printStackTrace()
                    callback.onError("连接失败: ${e.message}")
                }

                override fun onResponse(call: Call, response: Response) {
                    try {
                        LogUtils.e("DefaultChatService", "收到响应: ${response.code}")
                        if (!response.isSuccessful) {
                            val errorBody = response.body?.string()
                            LogUtils.e("DefaultChatService", "错误响应: $errorBody")
                            callback.onError("服务器错误: ${response.code}, $errorBody")
                            return
                        }

                        response.body?.source()?.use { source ->
                            while (!source.exhausted()) {
                                val line = source.readUtf8Line() ?: break
                                LogUtils.e("DefaultChatService", "收到数据: $line")
                                
                                if (line.startsWith("data: ")) {
                                    val jsonData = line.substring(6).trim()
                                    if (jsonData == "[DONE]") {
                                        callback.onPartialResponse("", true)
                                        return
                                    }

                                    try {
                                        val jsonResponse = JSONObject(jsonData)
                                        val choices = jsonResponse.getJSONArray("choices")
                                        if (choices.length() > 0) {
                                            val choice = choices.getJSONObject(0)
                                            val delta = choice.getJSONObject("delta")
                                            val content = delta.optString("content", "")
                                            val finishReason = choice.optString("finish_reason")
                                            
                                            LogUtils.e("DefaultChatService", "解析内容: content=$content, finishReason=$finishReason")
                                            
                                            if (content.isNotEmpty()) {
                                                callback.onPartialResponse(content, finishReason == "stop")
                                            } else if (finishReason == "stop") {
                                                callback.onPartialResponse("", true)
                                            }
                                        }
                                    } catch (e: Exception) {
                                        LogUtils.e("DefaultChatService", "解析JSON失败: ${e.message}")
                                        e.printStackTrace()
                                    }
                                }
                            }
                        }
                    } catch (e: Exception) {
                        LogUtils.e("DefaultChatService", "处理响应失败: ${e.message}")
                        e.printStackTrace()
                        callback.onError("处理响应失败: ${e.message}")
                    }
                }
            })
        } catch (e: Exception) {
            LogUtils.e("DefaultChatService", "发送消息失败: ${e.message}")
            e.printStackTrace()
            callback.onError("发送消息失败: ${e.message}")
        }
    }
} 